package gui;

import core.Map;
import core.Vertex;
import javafx.fxml.FXML;
import javafx.scene.control.*;

import javafx.event.ActionEvent;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Font;

import javax.imageio.IIOException;
import java.io.IOException;
import java.util.LinkedList;

public class Controller
{
    @FXML
    AnchorPane mapPane;
    @FXML
    Circle A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z;

    @FXML
    TextField startText;
    @FXML
    TextField endText;
    @FXML
    SplitMenuButton btWay;
    @FXML
    MenuItem btDrive;
    @FXML
    MenuItem btBus;
    @FXML
    MenuItem btWalk;
    @FXML
    TextArea infoText;
    @FXML
    Button btReset;
    @FXML
    Button btSearch;


    int mode=2;
    char start=0;
    char end=0;
    boolean tag;
    Map map;
    Vertex []vertexes;
    Circle []circles;
    LinkedList<Line>lines;

    private boolean needSetVertexes=true;
    public Controller()
    {
        map=new Map();
        vertexes=map.getVertexes();
        lines=new LinkedList<>();
    }
    public void setVertexes()
    {
        setCircles();
        for (int i=0;i<circles.length;i++)
        {
            vertexes[i].setOpoX(circles[i].getLayoutX());
            vertexes[i].setOpoY(circles[i].getLayoutY());
        }
        needSetVertexes=false;
    }
    public void setCircles()
    {
        circles= new Circle[]{A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z};
    }
    boolean isValid(String str)
    {
        return str.charAt(0) >= 'A' && str.charAt(0) <= 'Z'&&str.length()==1;
    }
    boolean isEmpty(String str)
    {
        return str == null || str.length() == 0;
    }
    public void setStart(KeyEvent keyEvent)
    {
        if (needSetVertexes)
            setVertexes();

        String startStr=startText.getText();

        if (isEmpty(startStr))
        {
            resetStartColor();
            start=0;
        }
        else if(isValid(startStr))
        {
            resetStartColor();
            start=startStr.charAt(0);
            circles[start-'A'].setFill(Paint.valueOf("YELLOW"));
        }
        else
        {
            startText.setText(start+"");
        }
    }
    public void setEnd(KeyEvent keyEvent)
    {
        if (needSetVertexes)
            setVertexes();

        String endStr=endText.getText();

        if (isEmpty(endStr))
        {
            resetEndColor();
            end=0;
        }
        else if(isValid(endStr))
        {
            resetEndColor();
            end=endStr.charAt(0);
            circles[end-'A'].setFill(Paint.valueOf("BLUE"));
        }
        else
        {
           endText.setText(end+"");
        }
    }

    public void resetStartColor()
    {
        if (start!=0)
            circles[start-'A'].setFill(Paint.valueOf("RED"));
    }
    public void resetEndColor()
    {
        if (end!=0)
            circles[end-'A'].setFill(Paint.valueOf("RED"));
    }
    public void clickVertex(MouseEvent mouseEvent)
    {
        Circle circle=(Circle)mouseEvent.getSource();
        char id=circle.getId().charAt(0);
        if (needSetVertexes)
        {
            setVertexes();
        }

        if (!tag)
        {
            tag=true;
            if(start!=0)
                circles[start-'A'].setFill(Paint.valueOf("RED"));

            start=id;
            startText.setText(id+"");
            circle.setFill(Paint.valueOf("YELLOW"));
        }
        else
        {
            tag=false;
            if (end!=0)
                circles[end-'A'].setFill(Paint.valueOf("RED"));
            end=id;
            endText.setText(id+"");
            circle.setFill(Paint.valueOf("BLUE"));
        }
    }

    public void walkMode(ActionEvent actionEvent)
    {
        mode=0;
        btWay.setText("walk");
    }
    public void driveMode(ActionEvent actionEvent)
    {
        mode=-1;
        btWay.setText("drive");
    }
    public void busMode(ActionEvent actionEvent)
    {
        mode=1;
        btWay.setText("bus");
    }


    public void search(ActionEvent actionEvent)
    {
        if (needSetVertexes)
        {
            setVertexes();
            needSetVertexes=false;
        }

        if (start==end&&start!=0)
        {
            Alert alert=new Alert(Alert.AlertType.ERROR,"ERROR:Start should be different from end!");
            alert.show();
        }
        else if (mode==2)
        {
            Alert alert=new Alert(Alert.AlertType.ERROR,"ERROR:Mode is Empty!");
            alert.show();
        }
        else
        {
            if (start!=0&&end!=0)
                method1();
            else if (start==0&&end==0)
                method3();
            else if (start==0)
                method2();
        }
    }
    public void setLines(Vertex vertex)
    {
        if (vertex.getPath()!=null)
        {

            Vertex path=vertex.getPath();
            setLines(path);

            Line line=new Line(path.getOpoX(),path.getOpoY(),vertex.getOpoX(),vertex.getOpoY());
            line.setStroke(Paint.valueOf("GREEN"));
            line.setStrokeWidth(4);

            lines.add(line);
        }
    }
    public void drawLine()
    {
        setLines(map.getEnd());
        for (Line line:lines)
            mapPane.getChildren().add(line);
    }
    public void method1()
    {
        map.method1(start,end,mode);
        resetLines();
        drawLine();
        map.setInfo();
        infoText.setText(map.getInfo());
    }
    public void method2()
    {
        try
        {
            map.generateFile2(end,mode);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        resetLines();
        infoText.setText(modeString()+"creat text file of vertex "+end);
    }
    public void method3()
    {
        try
        {
            map.generateFile3(mode);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        resetLines();
        infoText.setText(modeString()+"creat text file of all vertexes");
    }
    public String modeString()
    {
        switch (mode)
        {
            case -1:return "Drive Mode:\n";
            case 1:return "Bus Mode:\n";
            default:return "Walk Mode:\n";
        }
    }
    public void reset(ActionEvent actionEvent)
    {
        resetGraph();
        resetInfo();

        start=0;
        end=0;
        mode=2;
    }
    public void resetInfo()
    {
        startText.setText("");
        endText.setText("");
        btWay.setText("Way");
        infoText.setText("");
    }
    public void resetGraph()
    {
        reset2Ends();
        resetLines();
    }
    public void reset2Ends()
    {
        if (needSetVertexes)
            setVertexes();
        else if (start!=0&&end!=0)
        {
            circles[start-'A'].setFill(Paint.valueOf("RED"));
            circles[end-'A'].setFill(Paint.valueOf("RED"));
        }

    }
    public void resetLines()
    {
        for (Line line:lines)
            mapPane.getChildren().remove(line);

        lines.clear();
    }
}
